package com.itfitness.googlemappoi.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ScrollView;
import android.widget.Scroller;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;


/**
 * @ProjectName: ScrollerScrollLayout
 * @Package: com.example.scrollerscrolllayout
 * @ClassName: ScrollLayout
 * @Description: java类作用描述
 * @Author: 作者名
 * @CreateDate: 2021/8/23 17:20
 * @UpdateUser: 更新者：
 * @UpdateDate: 2021/8/23 17:20
 * @UpdateRemark: 更新说明：
 * @Version: 1.0
 */
public class ScrollLayout extends FrameLayout {

    private Scroller mScroller;
    private float mStartY;
    private int mMaxExOffset = 500; //展开后剩余的距离
    private int mChangeDirectionOffset = 200;//滑动可改变状态的距离
    private boolean mIsScroll;
    private ScrollDirection mScrollDirection;//滑动的方向
    private float mDirectionStartY;//用来判断滑动方向的Y
    private View mScrollView;
    private Status mStatus = Status.ORIGINAL;//当前的状态
    public ScrollLayout(@NonNull Context context) {
        this(context,null);
    }

    public ScrollLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public ScrollLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mMaxExOffset = (int) (h * 0.5);//展开剩余距离默认50%
    }

    private void init() {
        mScroller = new Scroller(getContext());
    }

    private static boolean isRecyclerViewTop(RecyclerView recyclerView) {
        if (recyclerView != null) {
            RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
            if(layoutManager instanceof GridLayoutManager){
                int firstVisibleItemPosition = ((GridLayoutManager) layoutManager).findFirstVisibleItemPosition();
                View childAt = recyclerView.getChildAt(0);
                if (childAt == null || (firstVisibleItemPosition == 0 &&
                        layoutManager.getDecoratedTop(childAt) == 0)) {
                    return true;
                }
            }else if (layoutManager instanceof LinearLayoutManager) {
                int firstVisibleItemPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
                View childAt = recyclerView.getChildAt(0);
                if (childAt == null || (firstVisibleItemPosition == 0 &&
                        layoutManager.getDecoratedTop(childAt) == 0)) {
                    return true;
                }
            }else if(layoutManager instanceof StaggeredGridLayoutManager){
                if(recyclerView.canScrollVertically(-1)){
                    return false;
                }else {
                    return true;
                }
            }
        }
        return false;
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        //子控件如果是ScrollView的话就判断是否触顶,并且当前状态是原始状态，如果不是在顶部就按默认的方式处理，
        if(mScrollView != null && mScrollView instanceof ScrollView && mScrollView.getScrollY() != 0 && mStatus == Status.ORIGINAL){
            return super.onInterceptTouchEvent(event);
        }else if (mScrollView instanceof RecyclerView && !isRecyclerViewTop((RecyclerView) mScrollView) && mStatus == Status.ORIGINAL) {
            return super.onInterceptTouchEvent(event);
        }else {
            switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    mIsScroll = false;
                    mStartY = event.getY();
                    mDirectionStartY = event.getY();
                    //如果是展开模式，则当触摸顶部空白区域的时候不拦截事件
                    if(mStatus == Status.EXPANSION && event.getY() < getHeight() - mMaxExOffset){
                        return mIsScroll;
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    float moveY = mStartY - event.getY();
                    //大于一定的距离才被认定是滑动
                    if(Math.abs(moveY) > 5 || mIsScroll){
                        mStartY = event.getY();
                        //增加边界处理
                        if(getScrollY() + moveY >= 0){
                            mIsScroll = false;
                            scrollTo(0, 0);
                        }else if(getHeight() + getScrollY() + moveY <= mMaxExOffset){
                            mIsScroll = false;
                            scrollTo(0, mMaxExOffset - getHeight());
                        }else {
                            mIsScroll = true;
                            scrollBy(0, (int) moveY);
                        }
                        float directionMoveY = mDirectionStartY - event.getY();
                        if(directionMoveY > 0){
                            mScrollDirection = ScrollDirection.UP;
                        }else {
                            mScrollDirection = ScrollDirection.DOWN;
                        }
                        return mIsScroll;
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    startScroll();
                    return mIsScroll;
            }
            return super.onInterceptTouchEvent(event);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //把事件转到onInterceptTouchEvent中处理
        onInterceptTouchEvent(event);
        return mIsScroll;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        for (int i = 0; i < getChildCount(); i++) {
            View childAt = getChildAt(i);
            if(childAt instanceof ScrollView){
                mScrollView = childAt;
                break;
            }else if(childAt instanceof RecyclerView){
                mScrollView = childAt;
                break;
            }

        }
    }

    private void startScroll() {
        if(mScrollDirection == ScrollDirection.DOWN){
            expansion();
        }else{
            original();
        }
        mIsScroll = false;
    }

    /**
     * 展开
     */
    private void expansion(){
        boolean changeStatus = Math.abs(getScrollY()) > mChangeDirectionOffset;
        int maxOffsetY = -(getHeight() - mMaxExOffset + getScrollY());
        mScroller.startScroll(0,getScrollY(),0,changeStatus ? maxOffsetY : -getScrollY());
        if(changeStatus){
            mStatus = Status.EXPANSION;
        }
    }
    /**
     * 关闭
     */
    private void original(){
        boolean changeStatus = (getHeight() - Math.abs(getScrollY())) - mMaxExOffset > mChangeDirectionOffset;
        int maxOffsetY = -(getHeight() - mMaxExOffset + getScrollY());
        mScroller.startScroll(0,getScrollY(),0,changeStatus ? -getScrollY() : maxOffsetY);
        if(changeStatus){
            mStatus = Status.ORIGINAL;
        }
    }
    public void setStatus(Status status){
        if(status == Status.EXPANSION){
            scrollTo(mScroller.getCurrX(),getHeight() - mMaxExOffset);
        }else {
            scrollTo(mScroller.getCurrX(),0);
        }
    }

    @Override
    public void computeScroll() {
        if(mScroller.computeScrollOffset()){
            scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
        }
        invalidate();
        super.computeScroll();
    }

    /**
     * 滑动的方向
     */
    public enum ScrollDirection{
        UP,//向上
        DOWN//向下
    }

    /**
     * 当前控件的状态
     */
    public enum Status{
        EXPANSION,//展开状态
        ORIGINAL//未展开（原始状态）
    }
}
